/** \file    thread.h
  * \brief   Object-oriented approach to threads manipulation;
  *			 It is safe to throw exceptions in the thread because they are catched by the class.
  * \date    2000 - 2003
  * \author  Fedor Chelnokov
  * \version $Header: /home/cscom1r4/cvsroot/cs/include/mswin/thread.h,v 1.4 2004/06/07 11:05:00 cscom1r4 Exp $
  */

#ifndef _thread_h_
#define _thread_h_

typedef void * HANDLE;

namespace mswin {

class thread
{
public:
	///the thread is created suspended (resume() it after construction),
	///if resume it here, then subclass may have no time to initialize data memebers and virtual table!
    thread(bool create = true);
    ~thread();

	void create(bool resume);
	bool created() const
		{ return _hthread != 0; }
    HANDLE handle() 
		{ return _hthread; }
    bool is_finished_ok() const
		{ return _finished_ok; }
	void restart_on_error(bool b)
		{ _restart_on_error = b; }
	bool restart_on_error() const
		{ return _restart_on_error; }

public: //to call from other threads
    void suspend();
    void resume();
    bool is_finished();
    bool wait_finish();
    ///use with caution in extreme situations
    void terminate();

public:
#ifdef _DEBUG
	/// the method must be called when the thread is already created,
	/// it seems that happens not immediately after CreateThread(...)
	void set_debug_name(const char * name);
#else
	void set_debug_name(const char *) { }
#endif

protected: //to overload by subclass
    virtual void run() = 0;
	///default implementation reports errors in std::clog
	virtual void report_error(const char * msg); 

private:
	///catches all C++ and Windows exceptions inside; may restart run() in the case of exception
	void safe_run();
	void exception_occured(const char * msg);

private:
    HANDLE _hthread;   ///< used while waiting thread finishing
#ifdef _DEBUG
	unsigned _thread_id;
#endif
    bool _finished_ok; ///< there was no exceptions during thread run;
	volatile bool _restart_on_error; ///< executes run() each time an exception is occurred

	friend unsigned __stdcall start_thread(void * arg);
};

} //namespace mswin

#endif //_thread_h_
